<template>
    <!-- 搜索 -->
    <div class="search">
        <label>根据姓名搜索：</label>
        <el-select @clear="clearSearchKey" v-model="searchKey" filterable remote clearable placeholder="🔍输入姓名搜索"
            :remote-method="remoteMethod" :loading="searchLoading" @change="searchChange">
            <el-option v-for="item in searchOptions" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
    </div>
    <!-- 添加按钮 -->
    <div class="add">
        <el-button type="primary" :icon="Plus" @click="addStu">添加项目</el-button>
    </div>
    <!-- excel导出 -->
    <div class="export">
        <el-button @click="exportExcel">
            <template #icon>
                <svg class="icon" aria-hidden="true">
                    <use xlink:href="#icon-excel"></use>
                </svg>
            </template>
            <template #default>
                导出Excel
            </template>
        </el-button>
    </div>
    <!-- 展示数据的表格 -->
    <div class="table">
        <el-table :data="tableData" border style="width: 100%" v-loading="tableLoading">
            <el-table-column prop="headimgurl" label="头像" width="140" align="center">
                <template v-slot="{ row }">
                    <el-avatar size="large" shape="square" :src="row.headimgurl"></el-avatar>
                </template>
            </el-table-column>
            <el-table-column prop="name" label="姓名" width="140" align="center" />
            <el-table-column prop="degree" label="学历" width="180" align="center" />
            <el-table-column prop="class" label="班级" width="180" align="center" />
            <el-table-column prop="productUrl" label="项目" width="160" align="center" />
            <el-table-column prop="cTime" label="创建时间" width="200" align="center" />
            <el-table-column prop="address" label="操作" width="260" align="center">
                <template v-slot="{ row }">
                    <el-button type="success" :icon="View" circle @click="view(row)" :disabled="!read1"/>
                    <el-button type="primary" :icon="Edit" circle @click="edit(row)" :disabled="!edit1"/>
                    <el-button type="danger" :icon="Delete" circle @click="del(row)" :disabled="!delete1"/>
                </template>
            </el-table-column>
        </el-table>
    </div>
    <!-- 分页 -->
    <div class="pageNataion">
        <el-pagination background layout="prev, pager, next" 
        :total="total" 
        :current-page="currentPage"
        :page-size="pageSize" 
        @current-change="pageChange" />
    </div>
    <!-- dialog弹窗组件 -->
    <qfdialog :title="dialogTitle" @closed="close" :visible="dialogVisible" :dialogFormData="dialogFormData"
        @validateSuccess="dialogFormvalidateSuccess" @dialogCancel="dialogCancel">
        <template v-slot:upload>
            <!-- 上传图片 -->
            <el-upload
                v-loading="uploadLoading"
                class="avatar-uploader"
                method="post"
                action="/api/students/uploadStuAvatar"
                :show-file-list="false"
                name="headimgurl"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload">
                <img v-if="imageUrl" :src="imageUrl" class="avatar" />
                <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
            </el-upload>
        </template>
    </qfdialog>
</template>
<script setup>
import { ElMessage,ElMessageBox } from 'element-plus'
// 引入dialog弹窗组件
import qfdialog from "@/components/dialog/index.vue"
// 引入接口
import * as api from "@/api/student"
import { ref, onMounted, reactive,toRefs } from "vue"
// 引入导出Excel的插件
import qee from "qf-export-excel"
// 引入图标
import {
    Delete,
    View,
    Edit,
    Plus,
} from '@element-plus/icons-vue'
// 引入路由
import { useRouter } from "vue-router"
// 引入store
import {useUser} from "@/store/users"
// 使用store
let userStore = useUser();
let router = useRouter()
// 得到本次登陆的权限
let btn = localStorage.getItem("permissionButtons")
// console.log(btn);
// ["add","edit","delete","read"]
// ["read"]
// 通过数组的includes属性，判断是否有这个权限
let read1 = btn.includes("read")
// console.log(read1)
let edit1 = btn.includes("edit")
// console.log(edit1)
let delete1 = btn.includes("delete")
// console.log(delete1);
// 搜索逻辑
// 搜索的数据
let searchOptions = ref([]);
// 搜索关键字
let searchKey = ref("")
// 搜索的加载动画
let searchLoading = ref(false)
// 搜索框输入之后会触发的方法，这里负责呈现搜索的联想数据
let remoteMethod = async (currentKeyWord) => {
    // console.log(currentKeyWord);
    if (!currentKeyWord) {
        return 
    }
    // 当请求数据时，开启加载动画
    searchLoading.value = true
    // console.log(searchKey.value);
    // console.log(currentKeyWord);
    // 这个三元的目的是为了保证用户在输入或者在选择的时候都能获取到搜索关键字
    // let key = searchKey.value ? searchKey.value : currentKeyWord
    // console.log(key);
    try {
        // 要搜索全部的数据，所以传递空字符count,默认搜索全部
        let res = await api.searchStuListApi(currentKeyWord, "")
        // 给联想的列表进行赋值操作
        // searchOptions.value = res.data.data.map(item => ({ value: item.name }))
        let repeatDatas = res.data.data.map(item => ({ value: item.name }))
        // 要去重操作
        let norepeatDatas = [];
        for (var i = 0; i < repeatDatas.length; i++) {
            // 声明一个开关
            let flag = true;
            for (var j = 0; j < norepeatDatas.length; j++) {
                if (repeatDatas[i].value === norepeatDatas[j].value) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                norepeatDatas.unshift(repeatDatas[i])
            }
        }
        // 去重之后对options进行赋值操作
        searchOptions.value = norepeatDatas
        // 关闭加载动画
        searchLoading.value = false
    } catch (e) {
        console.log(e);
        // 关闭加载动画
        searchLoading.value = false
    }
};
// 清空关键字之后的方法
let clearSearchKey = () => {
    console.log(currentPage.value);
    // 初始化数据，让页码重新回到第一页
    currentPage.value = 1;
}
// 用户选择了输入框的值之后，负责更新表格
let searchChange = async (key, page = 1, count = 10) => {
    // 打开表格的loading动画
    tableLoading.value = true
    // 获取用户点选的值
    console.log(searchKey.value);
    // 清空上次获取到的选项
    searchOptions.value = []
    try {
        let res = await api.searchStuListApi(searchKey.value, count,page)
        console.log(res);
        // 对表格数据的操作,将搜索的结果赋值给表格
        tableData.value = res.data.data
        // 关闭加载动画
        tableLoading.value = false
        // 对搜索结果进行分页
        setPageNation(res.data.total)
    } catch (e) {
        console.log(e);
        // 关闭加载动画
        tableLoading.value = false
    }
}
// 列表逻辑
// 表格数据
let tableData = ref([])
// 加载动画
let tableLoading = ref([])
// 封装一个方法，专门用于获取表格数据
let getStulist = async (page, count, classes) => {
    //开启加载动画
    tableLoading.value = true
    try {
        //请求列表数据
        let res = await api.getStulistApi(page, count, classes)
        console.log(res);
        // 给表格数据赋值
        tableData.value = res.data.data
        // 关闭加载动画
        tableLoading.value = false
        // 设置分页器的数量
        setPageNation(res.data.total)
    } catch (e) {
        console.log(e);
        // 关闭加载动画
        tableLoading.value = false
    }
}
// 分页处理
// 分页器的total属性，total表示一共多少条
let total = ref(1)
// 一页展示多少条
let pageSize = ref(10)
// 默认的页码
let currentPage = ref(1)
// 页码变更的时候
let pageChange = (inputCurrentPage) => {
    // 动态变更代码
    currentPage.value = inputCurrentPage
    // 判断有没有搜索关键字,如果有，那么就应该更新搜索的分页结果
    if (searchKey.value) {
        searchChange(null, inputCurrentPage)
    } else {
        // 不然才是拉取列表全部的数据
        getStulist(inputCurrentPage)
    }
}
// 专门修改分页器内容的方法
let setPageNation = (totalCount = 10, currentPage = 1, count = 10) => {
    total.value = totalCount;
    pageSize.value = count;
}
// 添加stu信息
// 声明dialogVisible控制dialog
// dialog标题
let dialogTitle = ref('增加数据')
let dialogVisible = ref(false)
let addStu = () => {
    // 重新打开dialog
    dialogVisible.value = true;
    dialogTitle.value = '增加数据'
}
// dialog的数据
let dialogFormData = reactive({
    class: {
        label: "班级",
        value: ""
    },
    name: {
        label: "姓名",
        value: ""
    },
    age: {
        label: "年龄",
        value: ""
    },
    city: {
        label: "城市",
        value: ""
    },
    degree: {
        label: "学历",
        value: ""
    },
    productUrl: {
        label: "项目地址",
        value: ""
    },
    description: {
        label: "描述",
        value: ""
    },
})
// dialog点击了确定按钮，并且表单校验通过触发的逻辑
let dialogFormvalidateSuccess = async (form) => {
    // console.log(valid);
    // console.log(dialogFormData);
    // 发起请求，将输入的内容传递给服务器
    let message = "添加成功"
    // 传递给后台的数据
    let params = {
        headimgurl: "",
        class: dialogFormData.class.value,
        name: dialogFormData.name.value,
        age: dialogFormData.age.value,
        city: dialogFormData.city.value,
        degree: dialogFormData.degree.value,
        productUrl: dialogFormData.productUrl.value,
        description: dialogFormData.description.value,
    }
    try {
         // 判断是否上传头像，如果上传了，就携带到params中去
         params.headimgurl = headimgurl.value ? headimgurl.value : ""
        let apiMethod = null;
        // 根据dialogTitle来区分要发送编辑请求还是发送增加请求
        switch (dialogTitle.value) {
            case '增加数据':
                apiMethod = api.addStuApi
                // 删除sId这条属性
                params.sId ? delete params.sId : ""
                break;
            case '编辑数据':
                apiMethod = api.updateStuApi;
                // 给params中添加sId属性
                params.sId = sId.value;
                // 更改提示信息
                message = '修改成功'
        }
        let res = await apiMethod(params)
        // console.log(res);
        // 添加成功
        // 1.提示，添加成功
        ElMessage({
            type: 'success',
            message
        })
        // 2.关掉dialog
        dialogVisible.value = false
        // 3.清空表单
        form.value.resetFields()
        // 4.更新列表
        getStulist()
    } catch (e) {
        ElMessage({
            type: 'error',
            message: e.toString()
        })
        console.log(e);
    }
}
// 点击dialog取消按钮触发的逻辑
let dialogCancel = () => {
    console.log('已经取消！');
    dialogVisible.value = false
}
// dialog关闭之后，要同步控制关闭属性的值
// 这么做的目的是为了处理点击空白区域或者右上角叉叉的时候，造成的后续dialog不能弹出的情况
let close = () => {
    dialogVisible.value = false
    // 将数据清空
    let keys = Object.keys(dialogFormData);
    keys.forEach(key => {
        dialogFormData[key].value = ""
    })
    // 清空头像的回显
    imageUrl.value=""
}
//编辑
// 声明一个变量，存储sId,便于编辑的时候传递给后端
let sId = ref("")
let edit = (row) => {
    // 1.打开dialog
    dialogVisible.value = true;
    // console.log(row);
    // 2.修改标题
    dialogTitle.value = '编辑数据'
    // 3.数据需要回显
    let keys = Object.keys(dialogFormData)
    keys.forEach(key => {
        dialogFormData[key].value = row[key]
    })
    //4.给sId赋值
    sId.value = row.sId
    // 更改全局的headimgurl这个字段，便于数据的传递
    headimgurl.value = row.headimgurl
    // 回显
    imageUrl.value = row.headimgurl
}
// 删除
let del = (row) => {
    // 发起删除请求
    // 获取当前这条数据的id,传递给后台就可以了
    // 1.交互，让用户确认是否删除
    ElMessageBox.confirm('此操作将永久删除这条数据'+row.name+',是否继续?','删除提示',{
        confirmButtonText:'确定',
        cancelButtonText:'取消',
        type:"warning"
    })
    .then(async()=>{
        // 2.发请求，删除数据
        try{
            let res = await api.delStuApi(row.sId)
            ElMessage({
                type:"success",
                message:'删除成功'
            })
            //更新列表
            getStulist()
        }catch(e){
            ElMessage({
                type:"error",
                message:'e.toString()'
            })
        }
    })
    .catch(()=>{
        ElMessage({
            type:'warning',
            message:"已取消删除"
        })
    })
}
// 上传文件
// 一个保存上传地址的变量
let imageUrl = ref()
// 声明headimgurl变量，用于将参数在表单dialog通过的时候，一并提交给后台
let headimgurl = ref("")
// 加载动画
let uploadLoading = ref(false)
// 上传成功的方法
let handleAvatarSuccess=(res,uploadFile)=>{
    //  console.log(res);
    if(res.state){
        //头像上传成功
        ElMessage({
            type:"success",
            message:res.msg
        }) 
        headimgurl.value = res.headimgurl;
        // console.log(headimgurl.value);
    }else{
        ElMessage({
            type:"error",
            message:res.msg
        })
    }
    // 关闭加载动画
    uploadLoading.value = false
    // console.log(uploadFile.raw);
    imageUrl.value = URL.createObjectURL(uploadFile.raw)
}
// 上传之前
let beforeAvatarUpload=(rawFile)=>{
    // 允许上传的文件类型
    let acceptType =['image/jepg','image/png']
    // 判断当前上传的文件类型是否包含在上面的数组中
    let isAccept = acceptType.includes(rawFile.type)
    if (!isAccept) {
        ElMessage.error('上传的文件只能是jpeg或者是png!')
        return false
    } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('上传文件的大小不能超过2MB!')
        return false
    }
    // 打开加载动画
    uploadLoading.value = true
    return true
}
onMounted(() => {
    getStulist()
})
// 导出Excel
let exportExcel = () =>{
    // 定义一个表头
    let titleSource=[
        {
            title:"姓名",
            key:"name"
        },
        {
            title:"年龄",
            key:"age"
        },
        {
            title:"头像地址",
            key:"headimgurl"
        },
        {
            title:"学历",
            key:"degree"
        },
        {
            title:"班级",
            key:"class"
        }
    ]
    qee(titleSource,tableData.value,'工资单')
}
//查看
let view=(row)=>{
    // console.log(row);
    // 声明一个对象，存储当前要查看的这一行的数据
    let stuIn ={
        headimgurl: row.headimgurl,
        class: row.class,
        name: row.name,
        age: row.age,
        city: row.city,
        degree: row.degree,
        productUrl: row.productUrl,
        description: row.description,
        cTime:row.cTime,
        sId:row.sId,
        _id:row._id,
    }
    // console.log(stuIn)
    // 存储用户信息
    userStore.$patch({
        stuInfo:stuIn
        })    
    // 直接获取当前产品的id,传递给下一个页面，然后跳转到预支付页面
    router.push("/stuManager/stuProfile")
}
</script>
<script>
export default {
    meta: {
        title: 'xyxmgl',
        name: '学员项目管理',
        routeName: "stuProduct",
        icon: "#icon-shuju1",
    }
}
</script>
<style scoped lang="less">
.search {
    margin: 30px 0 20px 0;
}

.add {
    margin-bottom: 30px;
}
.export{
    float: right;
    margin: 10px 20px 20px 0;
}
.el-pagination{
    justify-content: center;
}
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

